using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace Reactor.Messaging.ServiceBus
{
    /// <summary>
    /// Interface to define the operations on a MessagingChannel registry. MessagingChannel registries are responsible for 
    /// managing message destinations for the entire service bus.
    /// </summary>
    public interface IDestinationRegistry : IDisposable
    {
        /// <summary>
        /// Gets a value indicating whether this instance is passive.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is passive; otherwise, <c>false</c>.
        /// </value>
        bool IsPassive { get; }

        /// <summary>
        /// Gets a list of all subscribers known.
        /// </summary>
        /// <value>The subscribers.</value>
        /// <remarks>Access to this collection is thread safe.</remarks>
        ConcurrentBag<Subscriber> Subscribers { get; }

        /// <summary>
        /// Gets the subscriber instance for the current bus endpoint. 
        /// </summary>
        /// <value>The current subscriber.</value>
        /// <remarks>Manipulating the <see cref="Subscriber"/> instance directly is not a 
        /// thread safe operation. To remain thread safe, use the appropriate methods on 
        /// this <see cref="IDestinationRegistry"/> instance instead.</remarks>
        Subscriber InstanceSubscriber { get; }

        /// <summary>
        /// Appends data for the current endpoint's subscriptions.
        /// </summary>
        /// <param name="messagingChannel">The MessagingChannel.</param>
        /// <param name="messageTypes">The message types.</param>
        void AppendSubscriptionData(IMessagingChannel messagingChannel, Type[] messageTypes);

        /// <summary>
        /// Invalidates the specified subscription.
        /// </summary>
        void InvalidateSubscription(IMessagingChannel messagingChannel, Type messageType);

        /// <summary>
        /// Invalidates all subscriptions on non-durable destinations for the primary endpoint.
        /// </summary>
        void InvalidateSubscriptionsOnNonDurableDestinations();

        /// <summary>
        /// Registers the provided subscriber, making it's subscription details available.
        /// </summary>
        /// <param name="subscriber">The subscriber.</param>
        void RegisterSubscriber(Subscriber subscriber);

        /// <summary>
        /// Looks up subscriber's information. Uses the subscribers name to identify it.
        /// </summary>
        /// <param name="subscriberName">Name of the subscriber.</param>
        /// <returns>A constructed subscriber instance if one was found. Otherwise null.</returns>
        Subscriber LookupSubscriberByName(string subscriberName);

        /// <summary>
        /// Removes the specified subscriber from the registry.
        /// </summary>
        /// <param name="subscriberName">Name of the subscriber.</param>
        void RemoveSubscriberByName(string subscriberName);

        /// <summary>
        /// Gets the intended destinations for the specified message type.
        /// </summary>
        /// <exception cref="ArgumentNullException">Throws an <see cref="ArgumentNullException"/> if <paramref name="messageType"/> is null.</exception>
        /// <param name="messageType">Type of the message.</param>
        /// <returns>A list of intended destinations for the specified message type.</returns>
        IList<IMessagingChannel> GetIntendedDestinations(Type messageType);

        /// <summary>
        /// Initializes this instance. Implementers should discover subscription information at this time.
        /// </summary>
        void Initialize();

        /// <summary>
        /// Saves the snapshot of the current endpoint's subscription data.
        /// </summary>
        void SaveCurrentSubscriptionData();
    }
}